#include "CenaTeste.h"
#include "FPSCamera.h"
#include "StaticCamera.h"
#include "InputLayouts.h"
#include "AnimationShader.h"
#include "DummyPhysxObject.h"
#include "BallThrow.h"
#include "CookingInterface.h"
#include "UserStream.h"
#include "GeometryShaderSample.h"
#include "GeoShader.h"
#include <iostream>


CenaTeste::CenaTeste(void)
{
	world = new IWorld( new PhysxWorld() );		
	spriteRenderer = new SpriteRenderer();
	fps = new FPSMeasure();
	fps->Initialize();
}	

CenaTeste::~CenaTeste(void)
{ 	
}


IObject* testeobj;
void CenaTeste::Init(EngineStuff *engine)
{
	IScene::Init(engine);
	font.Initialize(L"Arial", 18, SpriteFont::Regular,true);

	spriteRenderer->Initialize();	

	PhysxWorld* pw = (PhysxWorld* ) world->GetPhysicWorld();
	assert(pw);		

	/*SIZE_T* size = new SIZE_T();
	char* bytes = EngineStuff::EAssetManagment->LoadCompiledShader("teste.fxo",size);

	ID3D11VertexShader * vb;
	HRESULT res = EngineStuff::EGraphicsDevice->CreateVertexShader(bytes ,*size,NULL,&vb);	*/

	ParticleSystem* ps = new ParticleSystem();
	ps->Init();
	world->AddParticleSystem(ps);

	/*triangleMesh, o LOAD eh para "cookar" o modelo (soh eh necessario 1 vez)
	classico cenario.x*/
	//{
	//	bool Load = false;
	//	IMesh* cen; 
	//	if(Load)
	//	{ 
	//		cen = engine->EAssetManagment->LoadAssimpSingleModel("C:/Users/tpastor/Desktop/Release/Code/PloobsEngine/Etapa1/Content/Model/cenario.X",true,true);			
	//		UserStream us = UserStream("cenario.bin",false);
	//		CookingInterface ci = CookingInterface(pw);			
	//		ci.ExtractMeshInfoAndCookTriangleMesh(cen,us,true);
	//	}
	//	else
	//	{
	//		cen = engine->EAssetManagment->LoadAssimpSingleModel("C:/Users/tpastor/Desktop/Release/Code/PloobsEngine/Etapa1/Content/Model/cenario.X",true,false);			
	//	}

	//	PhysxActor* cenActor = new PhysxActor();

	//	NxTriangleMesh* tm = pw->CreateTriangleMesh(UserStream("cenario.bin",true));				
	//	NxTriangleMeshShapeDesc shapeDesc;    
	//	shapeDesc.meshData= tm;    				
	//	//NxBodyDesc bodyDesc;    			
	//	cenActor->actorDescription.shapes.pushBack(&shapeDesc);
	//	//cenActor->actorDescription.body= &bodyDesc;    		
	//	cenActor->actorDescription.density = 1;		

	//	SimpleShader* shad = new SimpleShader();
	//	shad->Init("directional.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(cen->GetMeshType()));
	//	IObject* obb  = new IObject(cen ,shad,cenActor);
	//	world->AddObject(obb);		
	//}
	//
	///Terrain HeightMap
	//BitmapFileData* bData = engine->EAssetManagment->LoadBitmapData("C:/Users/tpastor/Documents/Visual Studio 2008/Projects/CudaTestes/heightmap01.bmp");
	//NxHeightFieldDesc heightFieldDesc;    
	//heightFieldDesc.nbColumns           = bData->width;     
	//heightFieldDesc.nbRows              = bData->height;    
	//heightFieldDesc.verticalExtent      = -1000;    
	//heightFieldDesc.convexEdgeThreshold = 0;
	////Allocate storage for samples.    
	//heightFieldDesc.samples             = new NxU32[bData->width*bData->height];
	//heightFieldDesc.sampleStride        = sizeof(NxU32);
	//NxU8* currentByte = (NxU8*)heightFieldDesc.samples;    
	//for (int j = 0; j < bData->height ; j++)        
	//{        
	//	for (int i = 0; i < bData->width ; i++)            
	//	{            
	//		int index = (bData->height * j) + i;
	//		NxHeightFieldSample* currentSample = (NxHeightFieldSample*)currentByte;            
	//		currentSample->height= bData->data[index].y /15; 
	//		//Desired height value. Signed 16 bit integer.            
	//		currentSample->materialIndex0 = 0;            
	//		currentSample->materialIndex1 = 0;            
	//		currentSample->tessFlag = 1;
	//		currentByte += heightFieldDesc.sampleStride;            
	//	}        
	//}    
	//NxHeightField* heightField = pw->CreateHeightField(heightFieldDesc);    
	////Data has been copied therefore free the buffer.  
	//delete[] heightFieldDesc.samples;

	//NxHeightFieldShapeDesc heightFieldShapeDesc;    
	//heightFieldShapeDesc.heightField     = heightField;    
	//heightFieldShapeDesc.heightScale     = 0.7f;    
	//heightFieldShapeDesc.rowScale        = 0.5f;    
	//heightFieldShapeDesc.columnScale     = 0.5f;    
	//heightFieldShapeDesc.materialIndexHighBits = 0;
	//heightFieldShapeDesc.holeMaterial = 2;
	//
	//PhysxActor* pactor = new PhysxActor();
	//pactor->actorDescription.shapes.pushBack(&heightFieldShapeDesc);    
	//pactor->actorDescription.globalPose.t = NxVec3(0,0,0);
	//
	//IMesh* terrain = new IMesh();
	//SimpleShader* tshad = new SimpleShader();
	//tshad->Init("effect.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(MeshTypeData::PositionTextureNormal));
	//IObject* obb  = new IObject(terrain ,tshad,pactor);
	//world->AddObject(obb);		

	//VertexData terrainVertexData;
	//PositionTextureNormalVertex* ptn;

	/////creating mesh
	//const NxHeightFieldShape * hfs = (const NxHeightFieldShape*)pactor->actor->getShapes()[0];
	//int numVertices = (hfs->getHeightField().getNbRows()-1)*(hfs->getHeightField().getNbColumns()-1)*3*2;
	//ptn = new PositionTextureNormalVertex[numVertices];	
	//terrainVertexData.positionTextureNormalVertex = ptn;

	//int vertIndex = 0;	
	//
	//for(NxU32 row = 0; row < hfs->getHeightField().getNbRows() - 1; row++)
	//{
	//	for(NxU32 column = 0; column < hfs->getHeightField().getNbColumns() - 1; column++)
	//	{
	//			NxTriangle tri;
	//			NxVec3 n;
	//			NxU32 triangleIndex;				

	//			triangleIndex = 2 * (row * hfs->getHeightField().getNbColumns() + column);

	//			if (hfs->getTriangle(tri, NULL, NULL, triangleIndex, true))
	//				{						
	//					n = (tri.verts[1]-tri.verts[0]).cross(tri.verts[2]-tri.verts[0]);
	//					n.normalize();
	//					
	//					XMFLOAT3 pos = XMFLOAT3(tri.verts[0].x,tri.verts[0].y,tri.verts[0].z);
	//					XMFLOAT3 norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							

	//					pos = XMFLOAT3(tri.verts[2].x,tri.verts[2].y,tri.verts[2].z);
	//					norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							

	//					pos = XMFLOAT3(tri.verts[1].x,tri.verts[1].y,tri.verts[1].z);
	//					norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							
	//					
	//				}
	//				triangleIndex++;
	//				
	//				if (hfs->getTriangle(tri, NULL, NULL, triangleIndex, true))
	//				{
	//					n = (tri.verts[1]-tri.verts[0]).cross(tri.verts[2]-tri.verts[0]);
	//					n.normalize();

	//					XMFLOAT3 pos = XMFLOAT3(tri.verts[0].x,tri.verts[0].y,tri.verts[0].z);
	//					XMFLOAT3 norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							

	//					pos = XMFLOAT3(tri.verts[2].x,tri.verts[2].y,tri.verts[2].z);
	//					norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							

	//					pos = XMFLOAT3(tri.verts[1].x,tri.verts[1].y,tri.verts[1].z);
	//					norm = XMFLOAT3(n.x,n.y,n.z);
	//					ptn[vertIndex].Normal = norm;
	//					ptn[vertIndex++].Position = pos;							

	//				}
	//	}
	//}
	//
	//terrain->Init(terrainVertexData,numVertices,MeshTypeData::PositionTextureNormal,XMMatrixIdentity(),NULL);
	//

	/*///Chaozito
	{
		SceneElements* ground = engine->EAssetManagment->LoadScene("C:/Users/tpastor/Desktop/Release/Code/PloobsEngine/Etapa1/Content/Model/block.X");
		assert(ground->Mesh.size() == 1);
		SimpleShader* s = new SimpleShader();
		s->Init("directional.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(ground->Mesh[0]->GetMeshType()));
		
		PhysxActor* dpo = new PhysxActor();
		NxBoxShapeDesc boxDesc;
		boxDesc.dimensions = NxVec3(1000,0.1f,1000);		
		dpo->actorDescription.shapes.pushBack(&boxDesc);		
		dpo->actorDescription.density		= 10.0f;		
		dpo->actorDescription.globalPose.t  = NxVec3(0,0,0);		
		dpo->actorDescription.flags |= NX_BF_KINEMATIC;
		*(dpo->ScaleTransform) =  XMMatrixScaling(1000,0.1f,1000);

		IObject* obb  = new IObject(ground->Mesh[0],s,dpo);
		world->AddObject(obb);		
	}*/

	//SceneElements* sceneL = engine->EAssetManagment->LoadScene("C:/Users/tpastor/Documents/3dsMax/export/boblampclean.md5mesh");
	/*SceneElements* sceneL = engine->EAssetManagment->LoadScene("C:/Users/tpastor/Desktop/KiloWatt/AnimationViewer/AnimationViewerContent/archer.x");

	for(int i = 0 ; i < sceneL->Mesh.size();i++)
	{		
		if(sceneL->Mesh[i]->Animated)
		{
			DummyPhysxObject* dpo = new DummyPhysxObject();
			AnimationShader* s = new AnimationShader(*InputLayouts::GetVertexLayout(sceneL->Mesh[i]->GetMeshType()));			
			IObject* obb  = new IObject(sceneL->Mesh[i],s,dpo);
			*dpo->Transform = XMMatrixScaling(5,5,5) * XMMatrixTranslation(50,100,0);	
			world->AddObject(obb);
			testeobj = obb;
		}
		else
		{			
			SimpleShader* s = new SimpleShader();
			s->Init("directional.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(sceneL->Mesh[i]->GetMeshType()));
			DummyPhysxObject* dpo = new DummyPhysxObject();
			*dpo->Transform = XMMatrixScaling(5,5,5) * XMMatrixTranslation(50,100,0);			 
			IObject* obb  = new IObject(sceneL->Mesh[i],s,dpo);
			world->AddObject(obb);
		}
	}
	
	vector<const char*> names = testeobj->GetMesh()->mAnimationController->GetAnimationNames();
	testeobj->GetMesh()->mAnimationController->setAnimation(names[0]);
	testeobj->GetMesh()->mAnimationController->SetAnimationStatus(AnimationStatus::Play);*/

	//{
	//	////geometry shader
	//	//IMesh* mesh = engine->EAssetManagment->LoadModel("","",MeshTypeData::PositionTextureNormal,MODEL_BOX,false);		
	//	IMesh* mesh = engine->EAssetManagment->LoadAssimpSingleModel("C:/Users/tpastor/Desktop/Release/Code/PloobsEngine/Etapa1/Content/Model/ton.X",true,true);			
	//	GeometryShaderSample* s = new GeometryShaderSample(mesh->GetMeshType());	
	//	//GeoShader* s = new GeoShader(mesh->GetMeshType());
	//	//SimpleShader* s = new SimpleShader();
	//	//s->Init("directional.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(mesh->GetMeshType()));
	//	DummyPhysxObject* dpo = new DummyPhysxObject();		
	//	XMMATRIX* tf =  (XMMATRIX* )_aligned_malloc(sizeof(XMMATRIX),16);
	//	*tf = XMMatrixTranslation(0,50,80) ;
	//	*dpo->Transform =  *mesh->Transformation * *tf;
	//	IObject* obb  = new IObject(mesh ,s,dpo);
	//	world->AddObject(obb);
	//}
	//{
	//	////geometry shader
	//	//IMesh* mesh = engine->EAssetManagment->LoadModel("","",MeshTypeData::PositionTextureNormal,MODEL_BOX,false);		
	//	IMesh* mesh = engine->EAssetManagment->LoadAssimpSingleModel("C:/Users/tpastor/Desktop/Release/Code/PloobsEngine/Etapa1/Content/Model/ton.X",true,true);			
	//	//GeometryShaderSample* s = new GeometryShaderSample(mesh->GetMeshType());	
	//	//SimpleShader* s = new SimpleShader();
	//	//s->Init("directional.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::GetVertexLayout(mesh->GetMeshType()));
	//	GeoShader* s = new GeoShader(mesh->GetMeshType());
	//	DummyPhysxObject* dpo = new DummyPhysxObject();		
	//	XMMATRIX* tf = (XMMATRIX* )_aligned_malloc(sizeof(XMMATRIX),16);
	//	*tf = XMMatrixTranslation(0,50,50) ;
	//	*dpo->Transform =  (*mesh->Transformation) * (*tf);
	//	IObject* obb  = new IObject(mesh ,s,dpo);
	//	world->AddObject(obb);

	//}


	//IMesh* mesh = engine->EMeshFactory->LoadModel("","",MeshTypeData::PositionTextureNormal,MODEL_QUAD,false);
	//IMesh* mesh = engine->EMeshFactory->LoadModel("","",MeshTypeData::PositionTextureNormal,MODEL_BOX,false);		
	///http://forums.create.msdn.com/forums/p/62501/384004.aspx
	///Para o SSE operar, a memoria tem q tar alinhada, alocacao continua ...,  se nao, da Acess VIOLATION >.<
	///camera = (Camera*) _aligned_malloc(sizeof(Camera), 16);
	///Tem Overload do New
	FPSCamera* camera = new(16) FPSCamera;		
	camera->SetPerspectiveProjection(XM_PIDIV4, EngineStuff::g_WindowWidth / (FLOAT)EngineStuff::g_WindowHeight, 1.0f, 3000.0f);	
	camera->moveSpeed = 0.1f;	
	world->SetCamera(camera);

	AddUpdateable(new BallThrow(world));

	/*IHudElement* element;
	Image2D* image;
	image = new Image2D(1.0f, 3000.0f);
	bool b= image->Initialize("brickwork.jpg",100,100);
	ImageShader* ishader;
	ishader = new ImageShader();
	ishader->Init("bitmap.fx","VS","vs_4_0","PS","ps_4_0",*InputLayouts::PositionTextureLayout);
	element = new IHudElement(image,ishader,700,500);
	AddHudElement(element);	*/
}

void CenaTeste::Draw(DWORD elapsedTime)
{
	fps->Frame();
	IScene::Draw(elapsedTime);

	spriteRenderer->Begin();

	int nfps = fps->GetFps();
	XMMATRIX transform = XMMatrixTranslation(25.0f, 50.0f, 0);        		
	
	char text[100];
	sprintf(text,"FPS : %d",nfps);
	spriteRenderer->RenderText(font,text,transform);	

	spriteRenderer->End();
}